﻿using FastMvc;
using FastMvc.Exceptions;
using FastMvc.Repositories;
using JQ.SAAS.DTO.OrgMenuSet;
using JQ.SAAS.Entity;
using JQ.SAAS.IService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JQ.SAAS.Service
{
    public class OrgMenuSetService : JQService, IOrgMenuSetService
    {
        private IRepository<org_menu_set> _Repository;
        private IRepository<sys_org_menu> _orgMenuRepository;

        public OrgMenuSetService(
            IRepository<org_menu_set> repository,
            IRepository<sys_org_menu> orgMenuRepository)
        {
            _Repository = repository;
            _orgMenuRepository = orgMenuRepository;
        }

        public async Task<MenuTreeNodeDto> AddTreeNode(MenuSetCreateDto createDto)
        {
            if (!string.IsNullOrEmpty(createDto.sParentId))
            {
                // 有父节点，先检查一下父节点
                var parent = await _Repository.FirstOrDefaultAsync(t => t.sId == createDto.sParentId);
                if (parent == null)
                    throw new ApiException("未知的父节点！");

                if (parent.sMenuType != 9)
                    throw new ApiException("仅可以在目录菜单下添加子菜单！");
            }

            org_menu_set _Set = MapTo<org_menu_set, MenuSetCreateDto>(createDto);
            if (createDto.sMenuType == 0)
            {
                // 添加一个页面菜单，检查有没有对应的权限
                var orgMenu = await _orgMenuRepository.FirstOrDefaultAsync(t => t.sMenuId == createDto.sMenuId && t.sMenuType == createDto.sMenuType);
                if (orgMenu == null)
                    throw new ApiException("当前机构无此页面的权限！"); // 请购买balabla。。。。

                _Set.SPermission = orgMenu.sMenuPermission;
            }

            _Set.sOrgId = this.OrgId;
            _Set.sOrgName = this.OrgName;
            await _Repository.InsertAsync(_Set);

            if (createDto.sMenuType == 0)
            {
                // 页面菜单，添加后，需要将对应的操作菜单也都添加进去
                var conMenus = _orgMenuRepository.GetAll(t => t.sMenuType == 1 && t.sParentMenuId == _Set.sMenuId);
                foreach (var cM in conMenus)
                {
                    org_menu_set cSet = new org_menu_set()
                    {
                        sId = Guid.NewGuid().ToString(),
                        sParentMenuId = _Set.sMenuId,
                        dCreateTime = DateTime.Now,
                        sMenuId = cM.sId,
                        sOrgId = this.OrgId,
                        sOrgName = this.OrgName,
                        sMenuType = 1,
                        sShowName = cM.sMenuName,
                    };

                    await _Repository.InsertAsync(cSet);
                }
            }

            return MapTo<MenuTreeNodeDto, org_menu_set>(_Set);
        }

        public async Task DeleteTreeNode(string sId)
        {
            var _Set = await _Repository.FirstOrDefaultAsync(t => t.sId == sId);
            if (_Set == null)
            {
                throw new ApiException("未知的配置Id！");
            }
            // 先获取自己以及全部下级的Id
            List<string> deIds = new List<string>() { _Set.sId };
            await GetAllChilds(_Set.sMenuId, deIds);

            await _Repository.DeleteAsync(t => deIds.Contains(t.sId));
        }

        private async Task GetAllChilds(string sMenuId, List<string> deIds)
        {
            var childs = (await _Repository.GetAllAsync(t => t.sParentMenuId == sMenuId)).Select(t => t.sMenuId).ToList();

            if (childs!=null && childs.Count > 0)
            {
                deIds.AddRange(childs);
                foreach (var child in childs)
                {
                    await GetAllChilds(child, deIds);
                }
            }
        }

        public async Task<List<PageMenuDto>> GetOrgPageMenus(PageMenuQueryDto query)
        {
            IEnumerable<sys_org_menu> Menus = null;
            if (query != null && !string.IsNullOrEmpty(query.Name))
            {
                Menus = await _orgMenuRepository.GetAllAsync(t => t.sMenuName.Contains(query.Name) && t.sMenuType == 0);
            }
            else
            {
                Menus = await _orgMenuRepository.GetAllAsync(t=> t.sMenuType == 0);
            }
            return Menus.Select(t => MapTo<PageMenuDto, sys_org_menu>(t)).ToList();
        }

        public async Task<List<MenuTreeNodeDto>> GetOrgSetTree()
        {
            var allMenus = await _Repository.GetAllAsync();

            var dtoList = allMenus.Where(t => string.IsNullOrEmpty(t.sParentMenuId))
                                                .Select(t => MapTo<MenuTreeNodeDto, org_menu_set>(t))
                                                .ToList();

            foreach(var dto in dtoList)
            {
                await SetTreeChild(dto, allMenus);
            }

            return dtoList.ToList();
        }

        public async Task<MenuTreeNodeDto> UpdateTreeNode(string sId, MenuSetUpdateDto updateDto)
        {
            var oldSet = _Repository.FirstOrDefault(t => t.sId == sId);
            if (oldSet != null)
                throw new ApiException("未知的菜单配置!");

            if (oldSet.sMenuType == 0)
            {
                if (string.IsNullOrEmpty(updateDto.sMenuId))
                    throw new ApiException("不可将页面菜单的指向设置为空！");

                var orgMenu = await _orgMenuRepository.FirstOrDefaultAsync(t => t.sMenuId == updateDto.sMenuId && t.sMenuType == 0);
                if (orgMenu == null)
                    throw new ApiException("当前机构无此页面菜单的权限！"); // 请购买balabla。。。。

                oldSet.SPermission = orgMenu.sMenuPermission;
            }

            // 更新信息
            oldSet.sMenuId = updateDto.sMenuId;
            oldSet.dUpdateTime = DateTime.Now;
            oldSet.sShowIco = updateDto.sShowIco;
            oldSet.sShowName = updateDto.sShowName;
            oldSet.iSort = updateDto.iSort;

            await _Repository.UpdateAsync(oldSet);

            return MapTo<MenuTreeNodeDto, org_menu_set>(oldSet);
        }

        private async Task SetTreeChild(MenuTreeNodeDto dto, IEnumerable<org_menu_set> allMenus)
        {
            if (dto.sMenuType == 1) // 操作菜单，没有下级 
                return;
            dto.Child = allMenus.Where(t => t.sParentMenuId == dto.sMenuId)
                        .Select(t => MapTo<MenuTreeNodeDto, org_menu_set>(t))
                        .ToList();
            if (dto.Child != null)
            {
                foreach (var cd in dto.Child)
                {
                    await SetTreeChild(cd, allMenus);
                }
            }
        }
    }
}
